package com.pb.infra.oth.util;

import com.pb.infra.auth.entity.custom.PriviInterCustom;
import com.pb.infra.auth.entity.pbsys.SysOperationLogWithBLOBs;
import com.pb.infra.auth.service.PriviUserService;
// import com.pb.infra.auth.service.SysOptLogService;
import com.pb.infra.auth.service.SysOptLogService;
import com.pb.infra.oth.exception.AppAuthException;
import com.pb.infra.oth.exception.ErrorCode;
import io.jsonwebtoken.Claims;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.UUID;

/**
 * 处理系统日志
 *
 * @author chenjian
 * @date 2020/1/5
 */
@Aspect
@Component
@Slf4j
public class SysLogAspect {

    @Autowired
    private SysOptLogService logService;

    @Autowired
    private PriviUserService priviUserService;

    /**
     * jwttoken配置类
     */
    @Resource
    private JwtTokenConfig jwtTokenConfig;

    @Resource
    private RedisTemplate<String, Object> redisTemplate;

    @Pointcut("@annotation( com.pb.infra.oth.util.SysLog)")
    public void logPoinCut() {
    }

    /**
     * 日志表记录日志
     * @param joinPoint
     */
    @AfterReturning("logPoinCut()")
    public void saveSysLog(JoinPoint joinPoint) {
        try {
            Method method = ((MethodSignature) joinPoint.getSignature()).getMethod();
            SysLog sysLog = method.getAnnotation(SysLog.class);
            if (!StringUtil.isEmpty(joinPoint.getArgs()) && joinPoint.getArgs().length > 0) {
                log.info("\n功能名:{}\n类:{}\n方法:{}\n参数:{}", sysLog.menuName(),joinPoint.getTarget().getClass().getName(), method.getName(), joinPoint.getArgs()[0]);
            } else {
                log.info("\n功能名:{}\n类:{}\n方法:{}", sysLog.menuName(),joinPoint.getTarget().getClass().getName(), method.getName());
            }
            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            String token = request.getHeader(jwtTokenConfig.getHeader());
            Claims claims = jwtTokenConfig.getClaimByToken(token);
            String userId = (String)claims.get(jwtTokenConfig.getSub());
            UserInfo userInfo = (UserInfo)redisTemplate.opsForValue().get(token);
            if (StringUtil.isEmpty(userId)) {
                throw new AppAuthException(ErrorCode.ErrorCodeEnum.ACCESS_USER_INFO);
            }
            SysOperationLogWithBLOBs optLog = new SysOperationLogWithBLOBs();
            if (!Constant.SYSTEM_ADMIN.equals(userId)) {
                List<Map<String, Object>> list =  userInfo.getLogPosition();
                // List<Map<String, Object>> list =  priviUserService.selPosotion(userId);
                if (list != null && list.size() > 0) {
                    optLog.setPositionId(list.get(0).get("positionId").toString());
                }
                //optLog.setLogId(DateTimeUtil.getStrFromDate(new Date(), "yyyyMMddHHmmssSSS"));
                optLog.setLogId(UUID.randomUUID().toString().replace("-", ""));
                optLog.setOperationTime(DateTimeUtil.getStrFromDate(new Date(), "yyyy/MM/dd HH:mm:ss"));
                optLog.setTableName(sysLog.tableName());
                optLog.setOperationType(sysLog.action().toString());
                optLog.setOperationMenu(sysLog.menuName());
                switch (sysLog.action()) {
                    case ADD:
                        optLog.setNewJson(JsonUtils.toString(joinPoint.getArgs()[0]));
                        break;
                    case MOD:
                        optLog.setNewJson(JsonUtils.toString(joinPoint.getArgs()[0]));
                        break;
                    case DEL:
                        optLog.setOldJson(JsonUtils.toString(joinPoint.getArgs()[0]));
                        break;
                    default:
                        break;
                }
                logService.insert(optLog);
            }
        } catch (Exception e) {
            log.error("failed to save log.", e);
        }
    }

}
